import 'package:dio/dio.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:naira_card/public.dart';

class HttpUtil {
  late Dio _dio;
  final Map<String, CancelToken> _map = {};
  final BaseOptions _options = getDefOptions();
  final Connectivity _connectivity = Connectivity();

  static final HttpUtil _singleton = HttpUtil._internal();

  static HttpUtil getInstance() {
    return _singleton;
  }

  factory HttpUtil() {
    return _singleton;
  }

  HttpUtil._internal() {
    _dio = Dio(_options);
  }

  Dio getDio() {
    return _dio;
  }

  /// 校验 网络异常
  Future<bool> isNetWorkAvailable() async {
    var connectivityResult = await _connectivity.checkConnectivity();
    if (connectivityResult.contains(ConnectivityResult.mobile) ||
        connectivityResult.contains(ConnectivityResult.wifi)) {
      return true;
    } else {
      return false;
    }
  }

  Future<T> request<T>(
    String url, {
    data,
    queryParameters,
    method = "get",
    headers,
    onReceiveProgress,
  }) async {
    bool isNetWork = await isNetWorkAvailable();
    if (!isNetWork) {
      debugPrint('=== HTTP请求失败: 网络异常 ===');
      return Future.error(
        DioException(
          type: DioExceptionType.unknown,
          error: "网络异常",
          requestOptions: RequestOptions(path: url),
        ),
      );
    }
    CancelToken cancelToken = CancelToken();

    ///保存token
    _map[url] = cancelToken;

    Options options = Options(method: method, headers: headers);

    try {
      Response response = await _dio.request(
        url,
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
        onReceiveProgress: onReceiveProgress,
      );

      if (response.statusCode == HttpStatus.ok) {
        if (response.data['code'] == '00000') {
          return Future.value(response.data);
        } else {
          //链接到服务器成功 但是接口业务处理报错
          debugPrint('=== HTTP请求失败: ${response.data['message']} ===');
          return Future.error(
            DioException(
              requestOptions: response.requestOptions,
              response: response,
              message: response.data['message'],
              type: DioExceptionType.badResponse,
            ),
          );
        }
      } else {
        // 即使状态码不是200也尝试解析响应
        debugPrint('=== HTTP状态码错误: ${response.statusCode} ===');
        return Future.error(
          DioException(
            requestOptions: response.requestOptions,
            response: response,
            message: "HTTP status code error: ${response.statusCode}",
            type: DioExceptionType.badResponse,
          ),
        );
      }
    } on DioException catch (e) {
      // 捕获Dio异常并详细记录
      if (e.response != null) {
        debugPrint('响应状态码: ${e.response?.statusCode}');
        debugPrint('响应头: ${e.response?.headers}');
        Toast.show('HTTP status code error: ${e.response?.statusCode}');
        return Future.error(
          DioException(
            requestOptions: e.requestOptions,
            response: e.response,
            message: "HTTP status code error: ${e.response?.statusCode}",
            type: DioExceptionType.badResponse,
          ),
        );
      } else {
        Toast.show('network error');
        return Future.error(
          DioException(
            requestOptions: e.requestOptions,
            response: e.response,
            message: e.message,
            type: DioExceptionType.connectionError,
          ),
        );
      }
    } catch (e) {
      // 捕获其他类型的异常
      debugPrint('=== HTTP未知异常: $e ===');
      return Future.error(e);
    }
  }

  void setConfig(HttpConfig config) {
    _mergeOption(config.options);
    _dio.options = _options;
    if (config.interceptorsWrapper != null) {
      _dio.interceptors.clear();
      _dio.interceptors.add(config.interceptorsWrapper as InterceptorsWrapper);
    }
  }

  static BaseOptions getDefOptions() {
    BaseOptions options = BaseOptions();
    options.contentType = "application/json";
    options.connectTimeout = Duration(
      milliseconds: 1000 * 10,
    ); // 修复为正确的Duration对象
    options.receiveTimeout = Duration(
      milliseconds: 1000 * 20,
    ); // 修复为正确的Duration对象
    // 添加允许的HTTP状态码，避免404等错误直接抛出异常
    options.validateStatus = (status) {
      return status! < 500; // 允许任何小于500的状态码
    };
    return options;
  }

  void _mergeOption(BaseOptions opt) {
    _options.method = opt.method;
    _options.headers = (Map.from(_options.headers))..addAll(opt.headers);
    _options.baseUrl = opt.baseUrl;
    _options.connectTimeout = opt.connectTimeout;
    _options.receiveTimeout = opt.receiveTimeout;
    _options.responseType = opt.responseType;
    _options.extra = (Map.from(_options.extra))..addAll(opt.extra);
    _options.contentType = opt.contentType ?? _options.contentType;
    _options.validateStatus = opt.validateStatus;
    _options.followRedirects = opt.followRedirects;
  }

  void cancelRequest(String url) {
    _map[url]?.cancel(url);
  }
}

class HttpConfig {
  HttpConfig({
    required this.options,
    this.interceptorsWrapper,
    this.pem,
    this.pKCSPath,
    this.pKCSPwd,
  });

  /// Options.
  BaseOptions options;

  /// 拦截
  InterceptorsWrapper? interceptorsWrapper;

  /// 详细使用请查看dio官网 https://github.com/flutterchina/dio/blob/flutter/README-ZH.md#Https证书校验.
  /// PEM证书内容.
  String? pem;

  /// 详细使用请查看dio官网 https://github.com/flutterchina/dio/blob/flutter/README-ZH.md#Https证书校验.
  /// PKCS12 证书路径.
  String? pKCSPath;

  /// 详细使用请查看dio官网 https://github.com/flutterchina/dio/blob/flutter/README-ZH.md#Https证书校验.
  /// PKCS12 证书密码.
  String? pKCSPwd;
}
